home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tech Arsenal 1
/
Tech Arsenal (Arsenal Computer).ISO
/
tek-19
/
intrlib1.zip
/
INTR_GR.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-01-26
|
37KB
|
1,050 lines
/******************************************************************************
* Low level graphics routines. *
* *
* Written by Gershon Elber, Oct. 1990 *
*******************************************************************************
* Supported device: *
* 1. CGA. *
* 2. EGA/VGA. *
* 2. Hercules. *
* 2. Super VGA. *
*******************************************************************************
* History: *
* 15 Oct 90 - Version 1.0 by Gershon Elber. *
******************************************************************************/
#include <string.h>
#include <stdio.h>
#include <math.h>
#include <mem.h>
#include <dos.h>
#include <io.h>
#include <graphics.h>
#include <conio.h>
#include <fcntl.h>
#include <ctype.h>
#include "intr_loc.h"
#include "mousedrv.h"
#include "intr_gr.h"
#define GR_LINE_LEN 80 /* Maximum chars read by GRGetGraphicLine. */
#define SVGA_SPECIAL 999 /* User installed BGI Super VGA driver. */
#define POINT_SIZE 0.05 /* Size of + marker drawn. */
#define POINT_TITLE 0.02 /* Distance between point title and + marker. */
#define CURSOR_IMAGE_X 24
#define CURSOR_IMAGE_Y 24
#define CURSOR_TYPE_STACK_SIZE 20 /* Size of stack to save cursor types. */
#define VIEW_PORT_STACK_SIZE 20 /* Depth of view port setting stack. */
#define TEXT_SETTING_STACK_SIZE 10 /* Depth of text setting stack. */
#define MAP_UP_X(x) ((((x) - GRPanFactorX) << GRZoomFactor) + GRWidth2)
#define MAP_UP_Y(y) ((((y) - GRPanFactorY) << GRZoomFactor) + GRHeight2)
#define MAP_DN_X(x) ((((x) - GRPanFactorX) >> GRIZoomFactor) + GRWidth2)
#define MAP_DN_Y(y) ((((y) - GRPanFactorY) >> GRIZoomFactor) + GRHeight2)
#define INVMAP_UP_X(x) ((((x) - GRWidth2) >> GRZoomFactor) + GRPanFactorX)
#define INVMAP_UP_Y(y) ((((y) - GRHeight2) >> GRZoomFactor) + GRPanFactorY)
#define INVMAP_DN_X(x) ((((x) - GRWidth2) << GRIZoomFactor) + GRPanFactorX)
#define INVMAP_DN_Y(y) ((((y) - GRHeight2) << GRIZoomFactor) + GRPanFactorY)
int GRScreenMaxX, GRScreenMaxY; /* The maximum resolution of the screen. */
int GRScreenMaxColors; /* The maximum # of colors available. */
IntrRType GRScreenAspect = 1.0; /* Screen aspect ratio (pixel width/height). */
int GRCurrentCursorX, GRCurrentCursorY; /* Cursor current position. */
int GRFontName, GRFontSize; /* Global information on font used. */
int GRDrawText; /* If can not zoom down text, force draw. */
int GRGraphMode = 0, GRGraphDriver = 0; /* What driver/mode are we in. */
static int GRScreenMaxX2, GRScreenMaxY2; /* Half of maximum resolution. */
static VoidPtr GRPutImage = NULL; /* If not null, used to save getimage. */
static char *GRBGIDriverPath = ""; /* Where to look for BGI drivers. */
static char *CursorImageBuffer; /* Cursor shape. */
static int ScreenCursorColor; /* Graphic and text (in graphic screen). */
static int OldStdOut; /* So we could recover it when exit from graph mode. */
static int GRScreenGraphicMode;
static char GRSVGAUserName[10];
static int GRSVGAUserMode = 1;
static int GRTextSize = 1; /* Current text size: 1 = 8x8, 2 = 16x16 etc.. */
static int GRWidth2 = 100;
static int GRHeight2 = 100;
static int GRMinX = 0;
static int GRMinY = 0;
static int GRZoomFactor = 0;
static int GRIZoomFactor = 0;
static int GRPanFactorX = 0;
static int GRPanFactorY = 0;
static struct text_info TextInfo; /* So we can restore starting text mode. */
static int ViewPortStackPtr = 0;
static struct viewporttype far ViewPortStack[VIEW_PORT_STACK_SIZE];
static int TextSettingStackPtr = 0;
static struct textsettingstype TextSettingStack[TEXT_SETTING_STACK_SIZE];
IntrInt2PtrFunc GlblGetChFunc = IntrGetEventWait;
static int GRGetKey(void);
/****************************************************************************
* Routine to be called for the user installed driver: *
****************************************************************************/
static int huge detectVGA(void)
{
return GRSVGAUserMode;
}
/****************************************************************************
* Routine to install the Super VGA information. *
* Note GraphDriver must be set to SVGA_SPECIAL for this to take affect. *
****************************************************************************/
void GRInstallSVGA(char *NameMode)
{
char *p;
p = strtok(NameMode, ".");
strcpy(GRSVGAUserName, p);
p = strtok(NULL, ".");
sscanf(p, "%d", &GRSVGAUserMode);
GRGraphDriver = SVGA_SPECIAL;
}
/****************************************************************************
* Routine to set the path to the BGI drivers location. *
****************************************************************************/
void GRSetBGIPath(char *BGIPath)
{
GRBGIDriverPath = strdup(BGIPath);
}
/****************************************************************************
* Routine to set default driver (0 autodetect). *
****************************************************************************/
void GRSetDefaultDriver(int GraphDriver)
{
GRGraphDriver = GraphDriver;
}
/****************************************************************************
* Routine to reset all the system to starting condition : *
****************************************************************************/
void GRInitGraph(void)
{
int IsSVGA = FALSE;
int i, j, GRScreenErrorCode;
unsigned char far
*BiosMode = (unsigned char far *) MK_FP(0x40, 0x49);
if (GRScreenGraphicMode) return;
gettextinfo(&TextInfo);
ViewPortStackPtr = 0; /* Make sure view port stack is empty. */
/* For some wierd reason, some machines waits much more than expected on */
/* the first delay. Lets do it now, so people will consider it part of */
/* the initialization (make it a feature...)... */
delay(1);
if (GRGraphDriver != SVGA_SPECIAL) {
if (GRGraphDriver == 0) {
/* Use autodetect feature of graphic library to see what we have.*/
detectgraph(&GRGraphDriver, &GRGraphMode);
if (GRGraphDriver < 0) {
IntrFatalError("Auto detect: No graphics device detected.");
}
}
}
/* Put in the following any graphic driver specific setup: */
switch (GRGraphDriver) {
case CGA:
GRGraphMode = CGAHI;
break;
case ATT400:
GRGraphMode = ATT400HI;
break;
case EGA:
GRGraphMode = EGAHI;
break;
case EGA64:
GRGraphMode = EGA64HI;
break;
case EGAMONO:
GRGraphMode = EGAMONOHI;
break;
case HERCMONO:
GRGraphMode = HERCMONOHI;
/* Use 2nd page as aux mem! */
GRPutImage = (VoidPtr) MK_FP(0xb800, 0x0000);
break;
case VGA:
GRGraphMode = VGAHI;
break;
case SVGA_SPECIAL:
IsSVGA = TRUE;
installuserdriver(GRSVGAUserName, detectVGA);
GRGraphDriver = DETECT;
GRGraphMode = GRSVGAUserMode;
break;
default:
IntrFatalError("Requested graphic device is not supported");
break;
}
initgraph(&GRGraphDriver, &GRGraphMode, GRBGIDriverPath);
if (IsSVGA) GRGraphDriver = SVGA_SPECIAL;
GRScreenErrorCode = graphresult(); /* Read result of initialization. */
if (GRScreenErrorCode != grOk) { /* Error occured during init. */
IntrFatalError("Graphics System Error: can not intialize.");
}
GRScreenMaxColors = getmaxcolor() + 1; /* Read maximum number of colors. */
ScreenCursorColor = (GRScreenMaxColors > 1 ? GRScreenMaxColors - 1 :
GRScreenMaxColors);
GRScreenMaxX = getmaxx(); /* Read size of screen. */
GRScreenMaxY = getmaxy();
GRCurrentCursorX = GRScreenMaxX2 = GRScreenMaxX / 2;
GRCurrentCursorY = GRScreenMaxY2 = GRScreenMaxY / 2;
getaspectratio(&i, &j); /* Read the hardware aspect. */
GRScreenAspect = ((IntrRType) i) / j;
setaspectratio(i, i); /* Disable the aspect ratio affect. */
GRFontName = DEFAULT_FONT;
GRFontSize = 1;
/* Prepare the cursor (Arrow) image : */
cleardevice();
GRSetColor(ScreenCursorColor);
GRSetLineStyle(SOLID_LINE, 0, NORM_WIDTH);
GRSLine(0, 0, CURSOR_IMAGE_X, CURSOR_IMAGE_Y);
j = CURSOR_IMAGE_X / 3;
for (i = 1; i <= 7; i++) GRSLine(0, 0, j, j + i);/* Draw the arrow head. */
j = CURSOR_IMAGE_Y / 3;
for (i = 1; i <= 7; i++) GRSLine(0, 0, j + i, j);
CursorImageBuffer = _IntrMalloc(imagesize(0, 0, CURSOR_IMAGE_X,
CURSOR_IMAGE_Y));
getimage(0, 0, CURSOR_IMAGE_X, CURSOR_IMAGE_Y, CursorImageBuffer);
GRClearAllScreen();
GRSetSTextStyle(DEFAULT_FONT, HORIZ_DIR, 1);
switch (GRGraphDriver) {
case CGA:
case ATT400:
case EGA:
case EGA64:
case EGAMONO:
case VGA:
MouseSetResolution(1000);
break;
case SVGA_SPECIAL:
MouseSetResolution(4000);
break;
case HERCMONO:
*BiosMode = 6;
/* Compensate on the text mode the mouse knows about as */
/* hercules is not supported by the mouse driver! */
MouseSetResolution(1000);
break;
}
GRScreenGraphicMode = TRUE;
i = open("nul", O_WRONLY); /* Redirect the stdout to nul: (no ^C...). */
fflush(stdout);
OldStdOut = dup(1);
dup2(i, 1);
close(i);
}
/****************************************************************************
* Routine to close and shutdown graphic mode : *
****************************************************************************/
void GRCloseGraph(void)
{
if (!GRScreenGraphicMode) return;
closegraph(); /* Return the system to text mode. */
GRScreenGraphicMode = FALSE;
dup2(OldStdOut, 1); /* Recover stdout to its regular status. */
close(OldStdOut);
textmode(TextInfo.currmode);
}
/****************************************************************************
* Routine to set line style parameters. *
****************************************************************************/
void GRSetLineStyle(int LineStyle, unsigned int Pattern, int Thickness)
{
setlinestyle(LineStyle, Pattern, Thickness);
}
/****************************************************************************
* Routine to set fill style parameters. *
****************************************************************************/
void GRSetFillStyle(int Pattern, int Color)
{
setfillstyle(Pattern, Color);
}
/****************************************************************************
* Routine to set write mode parameters. *
****************************************************************************/
void GRSetWriteMode(int DrawMode)
{
setwritemode(DrawMode);
}
/****************************************************************************
* Routine to set text horizontal and vertical justification. *
****************************************************************************/
void GRSetTextJustify(int HorizCenter, int VertCenter)
{
settextjustify(HorizCenter, VertCenter);
}
/****************************************************************************
* Routine to set zoom factor for drawing. *
* Zoom factor of 0 means regular drawing while each inc/decremenet zooms *
* up/down respectively by a factor of 2. *
****************************************************************************/
void GRSetZoomFactor(int ZoomFactor)
{
GRZoomFactor = ZoomFactor;
GRIZoomFactor = -GRZoomFactor;
}
/****************************************************************************
* Routine to set pan factors for drawing space. *
****************************************************************************/
void GRSetPanFactors(int PanFactorX, int PanFactorY)
{
GRPanFactorX = PanFactorX;
GRPanFactorY = PanFactorY;
}
/****************************************************************************
* Routine to set text drawing parameters, in drawing space. *
****************************************************************************/
void GRSetTextStyle(int GRFontName, int Direction, int Size)
{
GRTextSize = Size + GRZoomFactor;
settextstyle(GRFontName, Direction, 1 << (MAX(GRTextSize, 1) - 1));
}
/****************************************************************************
* Routine to set text drawing parameters, in screen space. *
****************************************************************************/
void GRSetSTextStyle(int GRFontName, int Direction, int Size)
{
settextstyle(GRFontName, Direction, Size);
}
/****************************************************************************
* Routine to set text drawing parameters. *
****************************************************************************/
unsigned GRGetImageBufferSize(int x1, int y1, int x2, int y2)
{
return imagesize(x1, y1, x2, y2);
}
/****************************************************************************
* Routine to set text drawing parameters. *
****************************************************************************/
void GRGetImageBuffer(int x1, int y1, int x2, int y2, VoidPtr Buffer)
{
getimage(x1, y1, x2, y2, Buffer);
}
/****************************************************************************
* Routine to set text drawing parameters. *
****************************************************************************/
void GRPutImageBuffer(int x1, int y1, VoidPtr Buffer)
{
putimage(x1, y1, Buffer, COPY_PUT);
}
/****************************************************************************
* Routine to XOR a rectangle area on screen using current color. *
****************************************************************************/
void GRXORRectangle(int x1, int y1, int x2, int y2)
{
int i;
struct linesettingstype lineinfo;
getlinesettings(&lineinfo);
setwritemode(XOR_PUT);
setlinestyle(SOLID_LINE, 0, NORM_WIDTH);
for (i = y1; i <= y2; i++)
line(x1, i, x2, i);
setwritemode(COPY_PUT);
setlinestyle(lineinfo.linestyle, lineinfo.upattern, lineinfo.thickness);
}
/****************************************************************************
* External reference for the mappings. *
****************************************************************************/
int GRMapX(int x)
{
return (GRZoomFactor > 0 ? MAP_UP_X(x) : MAP_DN_X(x)) + GRMinX;
}
int GRMapY(int y)
{
return (GRZoomFactor > 0 ? MAP_UP_Y(y) : MAP_DN_Y(y)) + GRMinY;
}
/****************************************************************************
* External reference for the inverse mapping. *
****************************************************************************/
int GRInvMapX(int x)
{
x -= GRMinX;
return (GRZoomFactor > 0 ? INVMAP_UP_X(x) : INVMAP_DN_X(x));
}
int GRInvMapY(int y)
{
y -= GRMinY;
return (GRZoomFactor > 0 ? INVMAP_UP_Y(y) : INVMAP_DN_Y(y));
}
/****************************************************************************
* Routine to draw a line, in Object spaces. *
****************************************************************************/
void GRLine(int x1, int y1, int x2, int y2)
{
if (GRZoomFactor > 0) {
moveto(MAP_UP_X(x1), MAP_UP_Y(y1));
lineto(MAP_UP_X(x2), MAP_UP_Y(y2));
}
else {
moveto(MAP_DN_X(x1), MAP_DN_Y(y1));
lineto(MAP_DN_X(x2), MAP_DN_Y(y2));
}
}
/****************************************************************************
* Routine to move to a new position, in Object space. *
****************************************************************************/
void GRMoveTo(int x, int y)
{
if (GRZoomFactor > 0)
moveto(MAP_UP_X(x), MAP_UP_Y(y));
else
moveto(MAP_DN_X(x), MAP_DN_Y(y));
}
/****************************************************************************
* Routine to draw to a new position, in Object space. *
****************************************************************************/
void GRLineTo(int x, int y)
{
if (GRZoomFactor > 0)
lineto(MAP_UP_X(x), MAP_UP_Y(y));
else
lineto(MAP_DN_X(x), MAP_DN_Y(y));
}
/****************************************************************************
* Routine to move to a new position, in Screen (pixels) space. *
****************************************************************************/
void GRSMoveTo(int x, int y)
{
moveto(x, y);
}
/****************************************************************************
* Routine to draw to a new position, in Screen (pixels) space. *
****************************************************************************/
void GRSLineTo(int x, int y)
{
lineto(x, y);
}
/****************************************************************************
* Routine to draw to a new position, in Screen (pixels) space. *
****************************************************************************/
void GRSLine(int x1, int y1, int x2, int y2)
{
line(x1, y1, x2, y2);
}
/****************************************************************************
* Routine to move to a new position relative to current one, as in Object *
* space. *
****************************************************************************/
void GRMoveRel(int x, int y)
{
if (GRZoomFactor > 0)
moverel(x << GRZoomFactor, y << GRZoomFactor);
else
moverel(x >> GRIZoomFactor, y >> GRIZoomFactor);
}
/****************************************************************************
* Routine to line to a new position relative to current one, as in Object *
* space. *
****************************************************************************/
void GRLineRel(int x, int y)
{
if (GRZoomFactor > 0)
linerel(x << GRZoomFactor, y << GRZoomFactor);
else
linerel(x >> GRIZoomFactor, y >> GRIZoomFactor);
}
/****************************************************************************
* Routine to move to a new position relative to current one, as in Screen *
* space (pixel coords.). *
****************************************************************************/
void GRSMoveRel(int x, int y)
{
moverel(x, y);
}
/****************************************************************************
* Routine to line to a new position relative to current one, as in Screen *
* space (pixel coords.). *
****************************************************************************/
void GRSLineRel(int x, int y)
{
linerel(x, y);
}
/****************************************************************************
* Routine to draw a new polyline and fill it if Fill, in screen space. *
****************************************************************************/
void GRPoly(int n, int *Points, int Fill)
{
int i, ii;
if (GRZoomFactor > 0)
for (i = 0; i < n; i++) {
ii = i << 1;
Points[ii] = MAP_UP_X(Points[ii]);
Points[ii + 1] = MAP_UP_Y(Points[ii + 1]);
}
else
for (i = 0; i < n; i++) {
ii = i << 1;
Points[ii] = MAP_DN_X(Points[ii]);
Points[ii + 1] = MAP_DN_Y(Points[ii + 1]);
}
if (Fill) {
/* There is a problem with BLACK color that fillpoly sometime does */
/* not clear the border properly, so we need to redo it by drawpoly. */
fillpoly(n, Points);
drawpoly(n, Points);
}
else
drawpoly(n, Points);
}
/****************************************************************************
* Routine to draw a bar, in drawing space. *
****************************************************************************/
void GRBar(int x1, int y1, int x2, int y2)
{
if (GRZoomFactor > 0)
bar(MAP_UP_X(x1), MAP_UP_Y(y1), MAP_UP_X(x2), MAP_UP_Y(y2));
else
bar(MAP_DN_X(x1), MAP_DN_Y(y1), MAP_DN_X(x2), MAP_DN_Y(y2));
}
/****************************************************************************
* Routine to draw a bar, in screen space. *
****************************************************************************/
void GRSBar(int x1, int y1, int x2, int y2)
{
bar(x1, y1, x2, y2);
}
/****************************************************************************
* Routine to draw a circle, in drawing space. *
****************************************************************************/
void GRCircle(int x, int y, int r)
{
if (GRZoomFactor > 0)
circle(MAP_UP_X(x), MAP_UP_Y(y), r << GRZoomFactor);
else
circle(MAP_DN_X(x), MAP_DN_Y(y), r >> GRIZoomFactor);
}
/****************************************************************************
* Routine to draw an arc, in drawing space. *
* As the Y axes is inverted the Angles should be inverted as well. *
****************************************************************************/
void GRArc(int x, int y, int StAngle, int EndAngle, int r)
{
if (GRZoomFactor > 0)
arc(MAP_UP_X(x), MAP_UP_Y(y), -EndAngle, -StAngle, r << GRZoomFactor);
else
arc(MAP_DN_X(x), MAP_DN_Y(y), -EndAngle, -StAngle, r >> GRIZoomFactor);
}
/****************************************************************************
* Routine to draw the given text in given drawing space coordinates. *
****************************************************************************/
IntrBType GRDrawingText(void)
{
return GRTextSize > 0 || GRDrawText;
}
/****************************************************************************
* Routine to draw the given text in given drawing space coordinates. *
****************************************************************************/
void GRText(int x, int y, char *s)
{
/* If text can not be zoom down and we are not forced to draw - dont. */
if (GRTextSize < 1 && !GRDrawText) return;
if (GRZoomFactor > 0)
outtextxy(MAP_UP_X(x), MAP_UP_Y(y), s);
else
outtextxy(MAP_DN_X(x), MAP_DN_Y(y), s);
}
/****************************************************************************
* Routine to draw the given text in given screen space coordinates. *
****************************************************************************/
void GRSText(int x, int y, char *s)
{
outtextxy(x, y, s);
}
/****************************************************************************
* Routine to draw the given text in given screen space coordinates. *
* A Black shadow is drawn for the given string. *
****************************************************************************/
void GRSTextShadow(int x, int y, int Color, char *s)
{
GRSetColor(BLACK);
outtextxy(x + 2, y + 2, s);
GRSetColor(Color);
outtextxy(x, y, s);
}
/****************************************************************************
* Routine to get string width in pixel. *
****************************************************************************/
int GRGetTextWidth(char *Str)
{
return textwidth(Str);
}
/****************************************************************************
* Routine to get string height in pixel. *
****************************************************************************/
int GRGetTextHeight(char *Str)
{
return textheight(Str);
}
/****************************************************************************
* Routine to push current font type and text attributes. *
****************************************************************************/
void GRPushTextSetting(void)
{
if (TextSettingStackPtr >= TEXT_SETTING_STACK_SIZE)
IntrFatalError("Text setting stack overflow.");
gettextsettings(&TextSettingStack[TextSettingStackPtr++]);
}
/****************************************************************************
* Routine to pop current font type and text attributes. *
****************************************************************************/
void GRPopTextSetting(void)
{
if (--TextSettingStackPtr < 0)
IntrFatalError("Text setting stack underflow.");
settextstyle(TextSettingStack[TextSettingStackPtr].font,
TextSettingStack[TextSettingStackPtr].direction,
TextSettingStack[TextSettingStackPtr].charsize);
settextjustify(TextSettingStack[TextSettingStackPtr].horiz,
TextSettingStack[TextSettingStackPtr].vert);
}
/****************************************************************************
* Routine to set color to color within range. *
****************************************************************************/
void GRSetColor(int Color)
{
if (Color >= GRScreenMaxColors)
Color = Color % (GRScreenMaxColors - 1) + 1;
setcolor(Color);
}
/****************************************************************************
* Routine to get current active color. *
****************************************************************************/
int GRGetColor(void)
{
return getcolor();
}
/****************************************************************************
* Routine to set one color index RGB values (EGA/VGA only). *
****************************************************************************/
void GRSetRGBPalette(int Index, int Red, int Green, int Blue)
{
setrgbpalette(Index, Red, Green, Blue);
}
/****************************************************************************
* Routine to draw a point on screen as marker + with a title : *
****************************************************************************/
void GRPutArrowCursor(int x, int y)
{
putimage(x, y, CursorImageBuffer, XOR_PUT);
}
/****************************************************************************
* Routine to draw a point on screen as marker + with a title : *
****************************************************************************/
void GRDrawPoint(int x, int y, char title[], int PointColor)
{
GRSetColor(PointColor);
GRSMoveTo(x + POINT_SIZE, y);
GRSLineTo(x - POINT_SIZE, y);
GRSMoveTo(x, y + POINT_SIZE);
GRSLineTo(x, y - POINT_SIZE);
GRSText(x + POINT_TITLE, y + POINT_TITLE, title);
}
/*****************************************************************************
* Routine to clear all the screen. *
*****************************************************************************/
void GRClearAllScreen(void)
{
setviewport(0, 0, GRScreenMaxX, GRScreenMaxY, FALSE);
cleardevice();
}
/*****************************************************************************
* Routine to clear given rectangle viewport. *
*****************************************************************************/
void GRClearViewPort(int x1, int y1, int x2, int y2)
{
struct viewporttype viewport;
getviewsettings(&viewport);
setviewport(x1, y1, x2, y2, TRUE);
clearviewport();
setviewport(viewport.left, viewport.top, viewport.right, viewport.bottom,
viewport.clip);
}
/*****************************************************************************
* Routine to set given rectangle viewport. *
*****************************************************************************/
void _GRSetViewPort(int x1, int y1, int x2, int y2)
{
setviewport(x1, y1, x2, y2, TRUE);
}
/*****************************************************************************
* Routine to set given rectangle viewport. *
*****************************************************************************/
void _GRSetViewPort2(int x1, int y1, int x2, int y2, IntrBType Clip)
{
setviewport(x1, y1, x2, y2, Clip);
}
/*****************************************************************************
* Routine to set given rectangle viewport. *
*****************************************************************************/
void GRGetViewPort(int *x1, int *y1, int *x2, int *y2)
{
struct viewporttype viewstruct;
getviewsettings(&viewstruct);
*x1 = viewstruct.left;
*x2 = viewstruct.right;
*y1 = viewstruct.top;
*y2 = viewstruct.bottom;
}
/*****************************************************************************
* Routine to set given rectangle viewport. *
*****************************************************************************/
void GRSetViewPort(int x1, int y1, int x2, int y2)
{
setviewport(x1, y1, x2, y2, TRUE);
GRWidth2 = (x2 - x1) / 2;
GRHeight2 = (y2 - y1) / 2;
GRMinX = x1;
GRMinY = y1;
}
/*****************************************************************************
* Routine to push current view port. *
*****************************************************************************/
void GRPushViewPort(void)
{
if (ViewPortStackPtr >= VIEW_PORT_STACK_SIZE)
IntrFatalError("View port stack overflow.");
getviewsettings(&ViewPortStack[ViewPortStackPtr++]);
}
/*****************************************************************************
* Routine to pop current view port. *
*****************************************************************************/
void GRPopViewPort(void)
{
if (--ViewPortStackPtr < 0)
IntrFatalError("View port stack underflow.");
setviewport(ViewPortStack[ViewPortStackPtr].left,
ViewPortStack[ViewPortStackPtr].top,
ViewPortStack[ViewPortStackPtr].right,
ViewPortStack[ViewPortStackPtr].bottom,
ViewPortStack[ViewPortStackPtr].clip);
GRWidth2 = (ViewPortStack[ViewPortStackPtr].right -
ViewPortStack[ViewPortStackPtr].left) / 2;
GRHeight2 = (ViewPortStack[ViewPortStackPtr].bottom -
ViewPortStack[ViewPortStackPtr].top) / 2;
GRMinX = ViewPortStack[ViewPortStackPtr].left;
GRMinY = ViewPortStack[ViewPortStackPtr].top;
}
/*****************************************************************************
* Routine to read one line terminated by <Enter> and visualized on graphic *
* screen. *
* Full line editing is supported which includes: *
* 1. RGRht and left arrow to move along the line. *
* 2. Delete to delete current character. *
* 3. Insert to toggle Insert/Overwrite mode. *
* 4. Backspace to delete character before current one. *
* 5. Home/End to move to beginning/End of string respectively. *
* 6. Return to accept current line. *
* 7. Esc to clear current line. *
* *
* Notes: *
* If s is not empty it is used as starting string. *
* Line is drawn starting from position x, y on screen, WindowLen positions. *
* s buffer is assumed to be of SLen length. *
*****************************************************************************/
void GRGetGraphicLine(int WindowID, int x, int y, char s[], int SLen,
int WindowLen, int ForeColor, int BackColor)
{
static int
Insert = TRUE;
int NextKey, Xstep, xt,
CursorPos = 0,
FirstVisible = 0,
FirstTime = TRUE,
Len = strlen(s),
EndOfString = FALSE;
char DisplayLine[GR_LINE_LEN];
struct textsettingstype oldtext;
_IntrWindowStruct
*Window = WindowID ? _IntrFindWndwUsingID(WindowID) : NULL;
CursorPos = Len;
gettextsettings(&oldtext);
settextstyle(DEFAULT_FONT, HORIZ_DIR, 1);
settextjustify(LEFT_TEXT, TOP_TEXT);
Xstep = textwidth("M"); /* Get the width in pixels of current font. */
while (!EndOfString) {
/* Can not display the whole string, so set first visible char: */
FirstVisible = CursorPos > WindowLen - 2 ? CursorPos - WindowLen + 2
: 0;
/* Prepare the part of s to be displayed: */
strncpy(DisplayLine, &s[FirstVisible], GR_LINE_LEN - 1);
DisplayLine[WindowLen] = 0;
GRSetColor(ForeColor);
outtextxy(x, y, DisplayLine);
xt = x + (CursorPos - FirstVisible) * Xstep;
if (Insert)
GRXORRectangle(xt, y + 7, xt + 7, y + 8);
else
GRXORRectangle(xt, y, xt + 7, y + 8);
if ((NextKey = GRGetKey()) != KEY_REFRESH || FirstTime) {
if (Insert)
GRXORRectangle(xt, y + 7, xt + 7, y + 8);
else
GRXORRectangle(xt, y, xt + 7, y + 8);
GRSetColor(BackColor); /* Erase the string and the cursor: */
outtextxy(x, y, DisplayLine);
}
FirstTime = FALSE;
switch (NextKey) {
case KEY_BSPACE:
if (CursorPos == 0) {
GRTone(1000, 100); /* Do some noise... */
break;
}
movmem(&s[CursorPos], &s[CursorPos - 1], Len - CursorPos + 1);
CursorPos--;
Len--;
break;
case KEY_DELETE:
if (CursorPos >= Len) {
GRTone(1000, 100); /* Do some noise... */
break;
}
movmem(&s[CursorPos + 1], &s[CursorPos], Len - CursorPos);
Len--;
break;
case KEY_RIGHT:
if (CursorPos >= Len) {
GRTone(1000, 100); /* Do some noise... */
break;
}
CursorPos++;
break;
case KEY_LEFT:
if (CursorPos <= 0) {
GRTone(1000, 100); /* Do some noise... */
break;
}
CursorPos--;
break;
case KEY_RETURN:
EndOfString = TRUE;
break;
case KEY_ESC:
Len = 0; /* Clear everything. */
CursorPos = 0;
s[0] = 0;
break;
case KEY_HOME:
CursorPos = 0;
break;
case KEY_END:
CursorPos = Len;
break;
case KEY_INSERT:
Insert = !Insert;
break;
case KEY_NONE:
GRTone(1000, 100); /* Do some noise... */
GRTone(500, 200);
break;
case KEY_REFRESH: /* Internal event to intr_lib. */
if (Window != NULL) {
_GRSetViewPort(Window -> BBox.Xmin, Window -> BBox.Ymin,
Window -> BBox.Xmax, Window -> BBox.Ymax);
x = TEXT_BORDER,
y = Window -> BBox.Ymax - Window -> BBox.Ymin -
TEXT_BORDER - GRGetTextHeight("M");
}
settextstyle(DEFAULT_FONT, HORIZ_DIR, 1);
settextjustify(LEFT_TEXT, TOP_TEXT);
break;
default: /* Regular ascii char. */
if (Insert) {
movmem(&s[CursorPos], &s[CursorPos + 1],
Len - CursorPos + 1);
Len++;
}
else if (CursorPos == Len)
Len++; /* We are on last character. */
s[CursorPos++] = NextKey;
if (CursorPos == Len) s[CursorPos] = 0;
break;
}
if (SLen <= Len - 1) { /* End of buffer - can not save more info. */
Len = SLen - 1;
if (CursorPos > Len) CursorPos = Len;
GRTone(1000, 100); /* Do some noise... */
}
}
settextstyle(oldtext.font, oldtext.direction, oldtext.charsize);
settextjustify(oldtext.horiz, oldtext.vert);
}
/*****************************************************************************
* Sets the function invoked to get a kbd event in GRGetKey. *
* NULL will recover the internal default - IntrGetEventWait. *
*****************************************************************************/
void GRSetGetKeyFunc(IntrInt2PtrFunc GetChFunc)
{
if (GetChFunc == NULL)
GlblGetChFunc = IntrGetEventWait;
else
GlblGetChFunc = GetChFunc;
}
/*****************************************************************************
* Get a key from keyboard, and translating operational keys into special *
* codes (>255). *
*****************************************************************************/
static int GRGetKey(void)
{
int x, y;
/* Detach the keyboard from moving the mouse so keyboard can be used to */
/* edit the input line instead. */
_IntrDetachKbdFromMouse = TRUE;
while (GlblGetChFunc(&x, &y) != INTR_EVNT_KEY);
_IntrDetachKbdFromMouse = FALSE;
if (x >= 256) {
switch (x - 256) { /* Extended code - get the next extended char. */
case 75:
return KEY_LEFT;
case 77:
return KEY_RIGHT;
case 71:
return KEY_HOME;
case 79:
return KEY_END;
case 83:
return KEY_DELETE;
case 82:
return KEY_INSERT;
case KEY_REFRESH - 256:
return KEY_REFRESH;
}
}
else {
switch (x) {
case 8:
return KEY_BSPACE;
case 10:
case 13:
return KEY_RETURN;
case 27:
return KEY_ESC;
default:
if isprint(x) return x;
}
}
return KEY_NONE;
}
/*****************************************************************************
* Routine to make some sound with given Frequency, Time milliseconds: *
*****************************************************************************/
void GRTone(int Frequency, int Time)
{
sound(Frequency);
delay(Time);
nosound();
}